package chen.web.forum;

import java.util.Date;
import java.util.List;

import org.springframework.jdbc.core.simple.SimpleJdbcTemplate;

import chen.web.DataSourceProvider;
import chen.web.IdEntity;
import chen.web.event.EventListener;
import chen.web.forum.SubjectCondition.Order;
import chen.web.forum.SubjectCondition.OrderBy;
import chen.web.forum.event.BasePostEvent;
import chen.web.forum.event.PostCheckedEvent;
import chen.web.forum.event.PostDeletedEvent;
import chen.web.forum.event.PostMovedEvent;
import chen.web.forum.event.PostPublishedEvent;
import chen.web.forum.event.PostRestoredEvent;
import chen.web.forum.event.PostType;
import chen.web.util.DateInt;

/**
 * 此类负责维护category类中的动态信息
 * @author chen
 *
 */
public class CategoryDynamicInfoListeners {

	private static SimpleJdbcTemplate simpleJdbcTemplate = new SimpleJdbcTemplate(DataSourceProvider.getDataSource());
	private static final String SQL_2 = "select count(*) from web_subject_reply where sub_id = ? and reply_dateline > ?";
	
	
	private static Category getCategory(IdEntity entity, PostType type){
		switch(type){
		case Subject :{
			Subject sub = (Subject)entity;
			return sub.getCategory();
		}
		case Reply :{
			Reply reply = (Reply)entity;
			return reply.getBelongSubject().getCategory();
		}
		}
		return null;
	}
	
	private static Category getCategory(BasePostEvent event){
		return getCategory(event.getEntity(), event.getPostType());
	}
	
	private static void increaseCount(BasePostEvent event){
		Category category = getCategory(event);
		PostType type = event.getPostType();
		CategoryDynamicInfo info = category.getDynamicInfo();
		switch(type){
		case Subject :{
			Subject subject = (Subject)event.getEntity();
			info.setPostCount(info.getPostCount() + 1 + subject.getReplyCount());
			info.setSubjectCount(info.getSubjectCount() + 1);
			Date today = CategoryDynamicInfo.today();
			//当天发布的主题
			if(subject.getDateline().after(today)){
				info.setTodayPostCount(info.getTodayPostCount() + 1 + subject.getReplyCount());
			} else { //非当天发布主题，计算出主题当天的回复
				int count = simpleJdbcTemplate.queryForInt(SQL_2, subject.getId(), DateInt.transform(today));
				info.setTodayPostCount(info.getTodayPostCount() + count);
			}
			break;
		}
		case Reply :{
			info.setPostCount(info.getPostCount() + 1);
			info.setTodayPostCount(info.getTodayPostCount() + 1);
			break;
		}
		}
	}
	
	private static void decreaseCount(BasePostEvent event){
		Category category = getCategory(event);
		//主题移动减少的是原栏目的数量
		if(event instanceof PostMovedEvent){
			category = ((PostMovedEvent)event).getSource();
		}
		PostType type = event.getPostType();
		CategoryDynamicInfo info = category.getDynamicInfo();
		switch(type){
		case Subject :{
			Subject subject = (Subject)event.getEntity();
			info.setPostCount(info.getPostCount() - 1 - subject.getReplyCount());
			info.setSubjectCount(info.getSubjectCount() - 1);
			Date today = CategoryDynamicInfo.today();
			//当天发布的主题
			if(subject.getDateline().after(today)){
				info.setTodayPostCount(info.getTodayPostCount() - 1 - subject.getReplyCount());	
			} else {	//非当天发布主题，计算出主题当天的回复
				int count = simpleJdbcTemplate.queryForInt(SQL_2, subject.getId(), DateInt.transform(today));
				info.setTodayPostCount(info.getTodayPostCount() - count);
			}
			break;
		}
		case Reply :{
			info.setPostCount(info.getPostCount() - 1);
			Reply reply = (Reply)event.getEntity();
			if(reply.getDate().after(CategoryDynamicInfo.today())){
				info.setTodayPostCount(info.getTodayPostCount() - 1);	
			}
			break;
		}
		}
	}
	
	private static enum Operation{increase, decrease};
	private synchronized static void modifyCount(BasePostEvent event, Operation operation){
		if(operation == Operation.increase)
			increaseCount(event);
		if(operation == Operation.decrease)
			decreaseCount(event);
	}
	
	public static class PostDeletedListener implements EventListener<PostDeletedEvent>{
		private TopicManager tm;
		public PostDeletedListener(TopicManager tm){
			this.tm = tm;
		}
		@Override
		public void listen(PostDeletedEvent event) {
			// TODO Auto-generated method stub
			boolean fakeDeleted = false;
			switch(event.getPostType()){
			case Subject :{
				fakeDeleted = ((Subject)event.getEntity()).isFakeDelete();
				break;
			}
			case Reply :{
				fakeDeleted = ((Reply)event.getEntity()).isFakeDelete();
				break;
			}
			}
			//已经假删除过了，此次真删除不操作
			if(fakeDeleted && !event.isFake()){
				return;
			}
			
			Date date = getPostDate(event);
			ForumAccount author = getAuthor(event);
			CategoryDynamicInfo info = getCategory(event).getDynamicInfo();
			//若删除的帖子是最后发表的,重新加载最后发表的帖子信息
			if(date.getTime() == info.getLastPostDate().getTime() && author.getId() == info.getLastPostAuthorId()){
				loadLastPostInfo(getCategory(event), tm);
			}
			modifyCount(event, Operation.decrease);
			CategoryDynamicInfoManager.updateDynamicInfo(getCategory(event));
		}
		
	}
	
	public static class PostCheckedListener implements EventListener<PostCheckedEvent>{

		@Override
		public void listen(PostCheckedEvent event) {
			// TODO Auto-generated method stub
			Date date = getPostDate(event);
			ForumAccount author = getAuthor(event);
			CategoryDynamicInfo info = getCategory(event).getDynamicInfo();
			//若审核后的帖子发表时间较近
			if(date.getTime() > info.getLastPostDate().getTime()){
				info.setLastPostAuthorId(author.getId());
				info.setLastPostAuthorNickname(author.getAccount().getNickname());
				info.setLastPostDate(date);	
			}
			modifyCount(event, Operation.increase);
			CategoryDynamicInfoManager.updateDynamicInfo(getCategory(event));
		}
	
	}
	
	public static class PostRestoredListener implements EventListener<PostRestoredEvent>{

		@Override
		public void listen(PostRestoredEvent event) {
			// TODO Auto-generated method stub
			Date date = getPostDate(event);
			ForumAccount author = getAuthor(event);
			CategoryDynamicInfo info = getCategory(event).getDynamicInfo();
			//若恢复的帖子发表时间较近
			if(date.getTime() > info.getLastPostDate().getTime()){
				info.setLastPostAuthorId(author.getId());
				info.setLastPostAuthorNickname(author.getAccount().getNickname());
				info.setLastPostDate(date);	
			}
			modifyCount(event, Operation.increase);
			CategoryDynamicInfoManager.updateDynamicInfo(getCategory(event));
		}
		
	}
	
	static ForumAccount getAuthor(BasePostEvent event){
		switch(event.getPostType()){
		case Subject : {
			Subject subject = (Subject)event.getEntity();
			return subject.getAuthor();
		}
		case Reply :{
			Reply reply = (Reply)event.getEntity();
			return reply.getAuthor();
		}
		}
		return null;
	}
	
	static Date getPostDate(BasePostEvent event){
		switch(event.getPostType()){
		case Subject : {
			Subject subject = (Subject)event.getEntity();
			return subject.getDateline();
		}
		case Reply :{
			Reply reply = (Reply)event.getEntity();
			return reply.getDate();
		}
		}
		return null;
	}
	
	public static class PostPublishedListener implements EventListener<PostPublishedEvent>{

		@Override
		public void listen(PostPublishedEvent event) {
			// TODO Auto-generated method stub
			//需要审核的帖子不计算在内
			switch(event.getPostType()){
			case Subject : {
				Subject subject = (Subject)event.getEntity();
				if(subject.isNeedChecking()) return; break;
			}
			case Reply :{
				Reply reply = (Reply)event.getEntity();
				if(reply.isNeedChecking()) return; break;
			}
			}
			ForumAccount lastPostAuthor = getAuthor(event);
			Date lastPostDate = getPostDate(event);
			CategoryDynamicInfo info = getCategory(event).getDynamicInfo();
			info.setLastPostAuthorId(lastPostAuthor.getId());
			info.setLastPostAuthorNickname(lastPostAuthor.getAccount().getNickname());
			info.setLastPostDate(lastPostDate);	
			modifyCount(event, Operation.increase);
			CategoryDynamicInfoManager.updateDynamicInfo(getCategory(event));
		}
	}
	
	public static class PostMovedListener implements EventListener<PostMovedEvent>{
		private TopicManager tm;
		public PostMovedListener(TopicManager tm){
			this.tm = tm;
		}
		@Override
		public void listen(PostMovedEvent event) {
			// TODO Auto-generated method stub
			ForumAccount author = getAuthor(event);
			Date date = getPostDate(event);
			CategoryDynamicInfo info = getCategory(event).getDynamicInfo();
			//若移走的帖子是最后发表的,重新加载最后发表的帖子信息
			if(date.getTime() == info.getLastPostDate().getTime() && author.getId() == info.getLastPostAuthorId()){
				loadLastPostInfo(getCategory(event), tm);
			}
			modifyCount(event, Operation.decrease);
			modifyCount(event, Operation.increase);
			CategoryDynamicInfoManager.updateDynamicInfo(event.getSource());
			CategoryDynamicInfoManager.updateDynamicInfo(getCategory(event));
		}
		
	}
	
	private static void loadLastPostInfo(Category category, TopicManager tm){
		CategoryDynamicInfo info = category.getDynamicInfo();
		//获取最后的帖子信息
		List<TopicInfo> topicInfoList = tm.getTopicInfoList(new SubjectCondition ().setCategory(category).setOrderBy(OrderBy.LastReplyDate).setOrder(Order.Desc), 0, 1);
		if(topicInfoList.size() > 0){
			TopicInfo topicInfo = topicInfoList.get(0);
			info.setLastPostAuthorId(topicInfo.getLastReplierId());
			info.setLastPostAuthorNickname(topicInfo.getLastReplierNickname());
			info.setLastPostDate(topicInfo.getLastReplyDate());
		} else {
			info.setLastPostAuthorId(0);
			info.setLastPostAuthorNickname(null);
			info.setLastPostDate(null);
		}
	}

}
